import {
  Body,
  Controller,
  Get,
  Param,
  Headers,
  Query,
  Post,
  Put,
  Delete,
  UseInterceptors,
  ClassSerializerInterceptor,
  Session,
  UnauthorizedException,
} from '@nestjs/common';
import {
  ApiBearerAuth,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';
import { IsAuth } from 'src/decorators/auth.decorator';
import { IResponseData, responseData } from 'src/utils/result';
import { MenuService } from './menu.service';
import { CreateMenuDto, MenuDto, UpdateMenuDto } from './menu.dto';
import { handleTree } from 'src/utils/tools';

@ApiTags('菜单模块')
@ApiBearerAuth()
@Controller('menu')
export class MenuController {
  constructor(private readonly menuService: MenuService) {}
  @ApiOperation({ summary: '查询所有菜单' })
  @ApiResponse({
    status: 200,
    description: '查询所有菜单',
    type: MenuDto,
  })
  @UseInterceptors(ClassSerializerInterceptor)
  @Get()
  @IsAuth('system:menu:list')
  async findAll(@Headers() headers): Promise<IResponseData> {
    const res = await this.menuService.getAll({
      order: {
        sort: 'ASC',
      },
    });
    return responseData({
      code: 100010,
      data: res,
      language: headers['language'],
    });
  }

  @ApiOperation({ summary: '查询用户菜单' })
  @ApiResponse({
    status: 200,
    description: '查询用户菜单',
    type: MenuDto,
  })
  @UseInterceptors(ClassSerializerInterceptor)
  @Get('userMenu')
  @IsAuth('system:menu:userMenu')
  async userMenu(
    @Session() session: Record<string, any>,
    @Headers() headers,
  ): Promise<IResponseData> {
    const user = session.userInfo;
    if (!user) throw new UnauthorizedException('请先登录');
    let menus: any[];
    // 是否超级管理员
    if (user.id === 1) {
      menus = await this.menuService.getAll({
        order: {
          sort: 'ASC',
        },
      });
    } else {
      const roles = user.roles.map((item) => ({
        id: item.id,
      }));
      menus = await this.menuService.getAll({
        where: {
          roles,
        },
        order: {
          sort: 'ASC',
        },
      });
    }
    return responseData({
      code: 100010,
      data: menus,
      language: headers['language'],
    });
  }

  @ApiOperation({ summary: '查询菜单详情' })
  @ApiResponse({
    status: 200,
    description: '查询菜单详情',
    type: MenuDto,
  })
  @UseInterceptors(ClassSerializerInterceptor)
  @Get(':id')
  @IsAuth('system:menu:detail')
  async find(
    @Param('id') id: number,
    @Headers() headers,
  ): Promise<IResponseData> {
    const res = await this.menuService.getOne({
      where: {
        id,
      },
    });
    return responseData({
      code: 100010,
      data: res,
      language: headers['language'],
    });
  }

  @Post()
  @IsAuth('system:menu:add')
  @ApiOperation({ summary: '创建菜单' })
  @ApiResponse({ status: 200, description: '操作成功' })
  async create(
    @Body() dto: CreateMenuDto,
    @Headers() headers,
  ): Promise<IResponseData> {
    if (dto.menu_type === 'M') {
      if (!dto.path.startsWith('/')) {
        throw new Error('菜单类型为目录时,路径以" / "开头');
      }
      dto.name =
        (dto.path as string).charAt(0).toUpperCase() +
        (dto.path as string).slice(1);
    }
    if (dto.menu_type === 'C') {
      dto.name = dto.component;
    }
    if (dto.is_frame === '1') {
      // 校验URL地址合法性
      const reg =
        /^(https?|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]$/i;
      if (reg.test(dto.path)) {
        dto.name = dto.path;
      } else {
        throw Error('外链的URL（路由）地址不合法！');
      }
    }
    const res = await this.menuService.create(dto);
    return responseData({
      code: 100020,
      data: res,
      language: headers['language'],
    });
  }

  @Put()
  @IsAuth('system:menu:update')
  @ApiOperation({ summary: '更新菜单' })
  @ApiResponse({ status: 200, description: '操作成功' })
  async update(
    @Body() dto: UpdateMenuDto,
    @Headers() headers,
  ): Promise<IResponseData> {
    if (dto.menu_type === 'M') {
      if (!dto.path.startsWith('/')) {
        throw new Error('菜单类型为目录时,路径以" / "开头');
      }
      dto.name =
        (dto.path as string).charAt(1).toUpperCase() +
        (dto.path as string).slice(2);
    }
    if (dto.menu_type === 'C') {
      dto.name =
        (dto.path as string).charAt(0).toUpperCase() +
        (dto.path as string).slice(1);
    }
    if (dto.is_frame === '1') {
      // 校验URL地址合法性
      const reg =
        /^(https?|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]$/i;
      if (reg.test(dto.path)) {
        dto.name = dto.path;
      } else {
        throw Error('外链的URL（路由）地址不合法！');
      }
    }
    const res = await this.menuService.update(dto);
    return responseData({
      code: 100030,
      data: res,
      language: headers['language'],
    });
  }

  @Delete()
  @IsAuth('system:menu:delete')
  @ApiOperation({ summary: '删除菜单' })
  @ApiResponse({ status: 200, description: '操作成功' })
  async delete(
    @Query('ids') query: string,
    @Headers() headers,
  ): Promise<IResponseData> {
    const { lists } = await this.menuService.getAll();
    const data = handleTree(lists);
    const ids = query.split(',');
    for (let i = 0; i < ids.length; i++) {
      if (data.obj[ids[i]].children.length) {
        throw new Error('含有子集，请先删除子集');
      }
    }

    const res = await this.menuService.delete(query);
    return responseData({
      code: 100040,
      data: res,
      language: headers['language'],
    });
  }
}
